#include <Arduino.h>
#include <math.h>

#include "pbl.h"

// 按键 端口 [GENERAL_PORT] 是否按下？
bool PBL::compareButtonStatus(int digitalPin) {
    pinMode(digitalPin, INPUT);
    return digitalRead(digitalPin) == LOW;
}

// 限位开关 端口 [GENERAL_PORT] 是否检测到物体？
bool PBL::compareLimitSwitchDetectObject(int digitalPin) {
    pinMode(digitalPin, INPUT);
    return digitalRead(digitalPin) == LOW;
}

// 人体热释 端口 [GENERAL_PORT] 是否检测到人？
bool PBL::compareHumanThermolysisDetectHuman(int digitalPin) {
    pinMode(digitalPin, INPUT);
    return digitalRead(digitalPin) == LOW;
}

// 1路触摸 端口 [GENERAL_PORT] 是否按下？
bool PBL::compareOneWayTouchStatus(int digitalPin) {
    pinMode(digitalPin, INPUT);
    return digitalRead(digitalPin) == LOW;
}

// 获取超声波 端口 [GENERAL_PORT] 的值（cm）
int PBL::getUltrasonicValue(int digitalPin, int analogPin) {
    pinMode(digitalPin, OUTPUT);
    pinMode(analogPin, INPUT);
    digitalWrite(digitalPin, LOW);
    delayMicroseconds(2);
    digitalWrite(digitalPin, HIGH);
    //产生一个10us的高脉冲去触发SR04
    delayMicroseconds(10);
    digitalWrite(digitalPin, LOW);
    // 检测脉冲宽度，注意返回值是微秒us
    double time = pulseIn(analogPin, HIGH);
    //计算出距离，输出的距离的单位是厘米cm
    double distance = time / 58.00;
    //把得到的距离值通过串口通信返回给电脑，通过串口监视器显示出来
    return distance;
}

// 获取滑动电阻 端口 [SPECIFIC_PORT] 的值
int PBL::getSlidingResistanceValue(int analogPin) {
    pinMode(analogPin, INPUT);
    return analogRead(analogPin);
}

// 获取土壤湿度 端口 [SPECIFIC_PORT] 的值
int PBL::getSoilMoistureValue(int analogPin) {
    pinMode(analogPin, INPUT);
    return analogRead(analogPin);
}

// 获取光照强度 端口 [SPECIFIC_PORT] 的值
int PBL::getLightIntensityValue(int analogPin) {
    pinMode(analogPin, INPUT);
    return analogRead(analogPin);
}

// 获取麦克风 端口 [SPECIFIC_PORT] 的值
int PBL::getMicrophoneValue(int analogPin) {
    pinMode(analogPin, INPUT);
    return analogRead(analogPin);
}

// 获取循迹 端口 [SPECIFIC_PORT] 的值
int PBL::getTrackingValue(int analogPin) {
    pinMode(analogPin, INPUT);
    return analogRead(analogPin);
}

// 振动马达 端口 [SPECIFIC_PORT] 功率 [VIBRATION_INTENSITY]
void PBL::setVibrationIntensity(int digitalPin, int vibrationIntensity) {
    pinMode(digitalPin, OUTPUT);
    analogWrite(digitalPin, vibrationIntensity);
}

// 直流电机 端口 [SPECIFIC_PORT] 功率 [DCMOTOR_SPEED]
void PBL::setDCMoterSpeed(int digitalPin, int analogPin, int dcmotorSpeed) {
    pinMode(digitalPin, OUTPUT);
    pinMode(analogPin, OUTPUT);
    if (dcmotorSpeed == 0) {
        digitalWrite(analogPin, LOW);
        digitalWrite(digitalPin, LOW);
    } else if (dcmotorSpeed > 0) {
        digitalWrite(analogPin, HIGH);
        analogWrite(digitalPin, 255 - abs(dcmotorSpeed));
    } else {
        digitalWrite(analogPin, LOW);
        analogWrite(digitalPin, abs(dcmotorSpeed));
    }
}

// 每分钟 [BEATS] 节拍
void PBL::setBeatsPerMinute(int beats) {
    beatPerMin = beats;
}

// 蜂鸣器 端口 [SPECIFIC_PORT] 播放音符 [NOTES]
void PBL::setBuzzerNote(int digitalPin, int notes) {
    pinMode(digitalPin, OUTPUT);
    tone(digitalPin, notes);
}

// 蜂鸣器 端口 [SPECIFIC_PORT] 播放音符 [NOTES] 节拍 [BEAT_NUMBERS]
void PBL::setBuzzerNoteBeat(int digitalPin, int notes, int beatNumebrs) {
    pinMode(digitalPin, OUTPUT);
    tone(digitalPin, notes);
    int delayTime;
    switch (beatNumebrs) {
        case 0: delayTime = 60000 / beatPerMin / 8; break;
        case 1: delayTime = 60000 / beatPerMin / 8 * 3 / 2; break;
        case 2: delayTime = 60000 / beatPerMin / 4; break;
        case 3: delayTime = 60000 / beatPerMin / 4 * 3 / 2; break;
        case 4: delayTime = 60000 / beatPerMin / 2; break;
        case 5: delayTime = 60000 / beatPerMin / 2 * 3 / 2; break;
        case 6: delayTime = 60000 / beatPerMin; break;
        case 7: delayTime = 60000 / beatPerMin * 3 / 2; break;
    }
    delay(delayTime - 50);
    noTone(digitalPin);
    delay(50);
}

// 蜂鸣器 端口 [SPECIFIC_PORT] 休止
void PBL::setBuzzerRest(int digitalPin) {
    pinMode(digitalPin, OUTPUT);
    noTone(digitalPin);
}

// 蜂鸣器 端口 [SPECIFIC_PORT] 休止节拍 [BEAT_NUMBERS]
void PBL::setBuzzerRestBeat(int digitalPin, int beatNumebrs) {
    pinMode(digitalPin, OUTPUT);
    noTone(digitalPin);
    int delayTime;
    switch (beatNumebrs) {
        case 0: delayTime = 60000 / beatPerMin / 8; break;
        case 1: delayTime = 60000 / beatPerMin / 8 * 3 / 2; break;
        case 2: delayTime = 60000 / beatPerMin / 4; break;
        case 3: delayTime = 60000 / beatPerMin / 4 * 3 / 2; break;
        case 4: delayTime = 60000 / beatPerMin / 2; break;
        case 5: delayTime = 60000 / beatPerMin / 2 * 3 / 2; break;
        case 6: delayTime = 60000 / beatPerMin; break;
        case 7: delayTime = 60000 / beatPerMin * 3 / 2; break;
    }
    delay(delayTime);
}

// 红 [RED] 绿 [GREEN] 蓝 [BLUE]
long PBL::getRGB(int red, int green, int blue) {
    return (long(red) << 16) + (green << 8) + (blue);
}

// 多态，红 [RED] 绿 [GREEN] 蓝 [BLUE]
long PBL::getRGB(String red, String green, String blue) {
    return (long(red.toInt()) << 16) + (green.toInt() << 8) + (blue.toInt());
}